package com.feilong.taglib.display.pager;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.feilong.commons.core.entity.Pager;
import com.feilong.commons.core.util.Validator;
import com.feilong.servlet.http.ParamUtil;
import com.feilong.tools.velocity.VelocityUtil;

/**
 * 分页工具类<br>
 * 该类主要是将url相关数据转成vm需要的数据,解析成字符串返回.
 * 
 * @author <a href="mailto:venusdrogon@163.com">金鑫</a>
 * @version 1.0 2010-5-26 下午11:50:10
 */
public final class PagerUtil{

	/**
	 * 解析vm模板 生成分页html代码
	 * 
	 * @param count
	 *            总数
	 * @param currentPageNo
	 *            当前页码
	 * @param pageSize
	 *            每页显示list 数量
	 * @param maxIndexPages
	 *            分页页码最多显示个数
	 * @param skin
	 *            皮肤,支持皮肤的功能,请参考 分页皮肤样式
	 * @param pageUrl
	 *            url,如http://localhost:8888/pager.htm
	 * @param pageParamName
	 *            url中关于分页页码的参数
	 * @param vmPath
	 *            velocity 模板地址
	 * @return 生成分页html代码
	 */
	public static String getPagerContent(
			int count,
			int currentPageNo,
			int pageSize,
			int maxIndexPages,
			String skin,
			String pageUrl,
			String pageParamName,
			String vmPath){
		// 有数据,不是空
		if (0 != count){
			Pager pager = new Pager(currentPageNo, pageSize, count);
			int allPageNo = pager.getAllPageNo();
			URI uri = URI.create(pageUrl);
			// 默认皮肤 digg
			if (Validator.isNullOrEmpty(skin)){
				skin = PagerParam.default_skin;
			}
			/** ******************************************************** */
			// 获得开始和结束的索引
			int[] startIteratorIndexAndEndIteratorIndexs = getStartIteratorIndexAndEndIteratorIndex(allPageNo, currentPageNo, maxIndexPages);
			/**
			 * 开始迭代索引编号
			 */
			int startIteratorIndex = startIteratorIndexAndEndIteratorIndexs[0];
			/**
			 * 结束迭代索引编号
			 */
			int endIteratorIndex = startIteratorIndexAndEndIteratorIndexs[1];

			// ****************************************************************************************
			Map<String, Object> contextKeyValues = new HashMap<String, Object>();
			contextKeyValues.put("count", count);
			// 皮肤
			contextKeyValues.put("skin", skin);
			contextKeyValues.put("uri", uri);
			// 当前页
			contextKeyValues.put("currentPageNo", currentPageNo);
			// 总页数
			contextKeyValues.put("allPageNo", allPageNo);
			// 前一页页码
			contextKeyValues.put("prePageNo", pager.getPrePageNo());
			// 后一页页码
			contextKeyValues.put("nextPageNo", pager.getNextPageNo());
			// 导航页码 开始号码
			contextKeyValues.put("startIteratorIndex", startIteratorIndex);
			// 导航页码 结束号码
			contextKeyValues.put("endIteratorIndex", endIteratorIndex);
			contextKeyValues.put("ParamUtil", ParamUtil.class);
			// 分页参数码
			contextKeyValues.put("pageParamName", pageParamName);
			String content = VelocityUtil.parseVMTemplateWithClasspathResourceLoader(vmPath, contextKeyValues);
			return content;
		}
		return "";
	}

	/**
	 * 获得当前分页数字,不带这个参数 或者转换异常 返回1
	 * 
	 * @param request
	 *            当前请求
	 * @param paramName
	 *            the param name
	 * @return 分页请求第几页,不带这个参数 或者转换异常 返回1
	 */
	public static Integer getCurrentPageNo(HttpServletRequest request,String paramName){
		Integer currentPageNo = ParamUtil.getParameterToInteger(request, paramName);
		// 不是空
		if (null != currentPageNo){
			return currentPageNo;
		}
		// 不带这个参数 或者转换异常 返回1
		return 1;
	}

	/**
	 * 获得开始和结束的索引.
	 * 
	 * @param allPageNo
	 *            总页数
	 * @param currentPageNo
	 *            当前页数
	 * @return 获得开始和结束的索引
	 * @author 金鑫
	 * @version 1.0 2010-5-31 上午06:03:53
	 */
	private static int[] getStartIteratorIndexAndEndIteratorIndex(int allPageNo,int currentPageNo,int maxIndexPages){
		// 最多显示多少个导航页码
		maxIndexPages = getAutoMaxIndexPages(allPageNo, maxIndexPages);
		/**
		 * 开始迭代索引编号
		 */
		int startIteratorIndex = 1;
		/**
		 * 结束迭代索引编号
		 */
		int endIteratorIndex = allPageNo;
		// 总页数大于最大导航页数
		if (allPageNo > maxIndexPages){
			// 当前页导航两边总数和
			int fenTwo = (maxIndexPages - 1);
			// 当前页左侧导航数
			int leftCount = fenTwo / 2;
			// 当前页右侧导航数
			int rightCount = (fenTwo % 2 == 0) ? leftCount : (leftCount + 1);
			// 当前页<=(左边页数+1)
			if (currentPageNo <= (leftCount + 1)){
				startIteratorIndex = 1;
				// 此时迭代结束为maxIndexPages
				endIteratorIndex = maxIndexPages;
			}else{
				// 如果当前页+右边页>=总页数
				if (currentPageNo + rightCount >= allPageNo){
					startIteratorIndex = allPageNo - maxIndexPages + 1;
					// 此时迭代结束为allPageNo
					endIteratorIndex = allPageNo;
				}else{
					startIteratorIndex = currentPageNo - leftCount;
					endIteratorIndex = currentPageNo + rightCount;
				}
			}
		}
		return new int[] { startIteratorIndex, endIteratorIndex };
	}

	/**
	 * 获得分页最大显示的分页码<br>
	 * 如果maxIndexPages 是0或者null,那么根据allpageNo,采用自动调节长度功能<br>
	 * 因为,如果页码大于1000的时候, 如果还是10页码的显示(1001,1002,1003,1004,1005,1006,1007,1008,1009,1010) 显示上面会很长 ,会打乱页面布局 <br>
	 * <ul>
	 * <li>当大于1000的页码 显示6个 即 1001,1002,1003,1004,1005,1006 类似于这样的</li>
	 * <li>当大于100的页码 显示8个 即 101,102,103,104,105,106,107,108 类似于这样的</li>
	 * <li>其余,默认显示10条</li>
	 * </ul>
	 * 
	 * @param allPageNo
	 *            分页总总页数,不解释地球人都知道
	 * @param maxIndexPages
	 *            表示手动指定一个固定的显示码<br>
	 *            如果不指定,或者是0 那么就采用自动调节的显示码
	 * @return 最大显示码
	 */
	private static int getAutoMaxIndexPages(int allPageNo,Integer maxIndexPages){
		if (Validator.isNullOrEmpty(maxIndexPages) || 0 == maxIndexPages){
			// 总页数超过1000的时候,自动调节导航数量的作用
			if (allPageNo > 1000){
				return 6;
			}else if (allPageNo > 100){
				return 8;
			}else{
				return 10;// 默认为10
			}
		}
		// 不是 0 或者null,直接返回指定的
		return maxIndexPages;
	}
}
